/*************************************************************************
                           Palette.c  -  description
                             -------------------
    début                : 15 Novembre 2012
*************************************************************************/

//---------- Réalisation du thread Palette (fichier Palette.c) -----

/////////////////////////////////////////////////////////////////  INCLUDE
//-------------------------------------------------------- Include système

#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <mqueue.h>
#include <sys/stat.h>
#include <errno.h>
#include <time.h>

//------------------------------------------------------ Include personnel
#include "../Outils/config.h"
#include "../Outils/simulation.h"
#include "palette.h"


void * Palette ()
{


	int bytes_read;
	unsigned int msgPrio = PRIO_MSG_L;
	int flagReprise=1;

	//Declarations des BAL
	mqd_t queue_versPalette;
	mqd_t queue_versStockage;
	mqd_t queue_versErreur;
	mqd_t queue_retErreur;
	mqd_t queue_versArchivage;

	int nbCartonMisEnPalette;
	int capacitePalette;
	int nbPlace;
	//Declaration des messages
	MSG_carton msgImp;
	MSG_carton msgErreurImp;
	MSG_carton msgPaletteOK;
	MSG_versArchivage msgPalette_archivage;
	MSG_versErreur msgErreur;
	MSG_retErreur msgRetErreur;

	//-------------------------------Phase initialisation--------------------------
	//ouverture de BAL_versPalette en lecture seule
	queue_versPalette =  mq_open(BAL_versPalette, O_RDONLY);

	//ouverture de BAL_versStockage en écriture seule
	queue_versStockage =  mq_open(BAL_versStockage, O_WRONLY);

	//ouverture de BAL_versArchivage en lecture seule
	queue_versArchivage =  mq_open(BAL_versArchivage, O_WRONLY);

	//ouverture de BAL_versErreur en écriture seule
	queue_versErreur =  mq_open(BAL_versErreur, O_WRONLY);

	//ouverture de BAL_retErreur en lecture seule
	queue_retErreur =  mq_open(BAL_retErreur, O_RDONLY);


	nbCartonMisEnPalette=0;


	//-------------------------------Phase moteur--------------------------
	for ( ; ; )
	{

	  //attente d'un message de Impression
	  bytes_read = mq_receive(queue_versPalette, (char*)&msgImp, sizeof(MSG_carton), NULL);

	  if (bytes_read == -1)
	  {
	   	perror("[Palette] Failed to recieve BAL_versPalette:");
	  }
	  else
	  {
		//lecture des messages
		int typeImp=msgImp.type;
		int numCartonImp=msgImp.numCarton;
		int numLotImp=msgImp.numLot;
		char typeProduitImp=msgImp.typeProduit;

		if (typeImp == FIN_APPLI || typeImp==FIN_PROD)
		{

			//ecriture du message msgErreurImp
			msgErreurImp.type=typeImp;
			msgErreurImp.numCarton=0;
			msgErreurImp.numLot=numLotImp;
			msgErreurImp.typeProduit=typeProduitImp;

			//envoi du message msgErreurImp à Stockage
			if (0 != mq_send(queue_versStockage,(const char*)&msgErreurImp,sizeof(MSG_carton),msgPrio))
			{
				perror ("[Palette] Failed to Send BAL_versStockage:");

			}

			//Fermeture des BAL
			mq_close (queue_versArchivage);
			mq_close (queue_versPalette); 
			mq_close (queue_versStockage); 
			mq_close (queue_versErreur);
			mq_close (queue_retErreur);
			pthread_exit(0);

		}
		else
		{
			//verif si changement palette pour detecter presence
			if (nbCartonMisEnPalette==0)
			{
				if(PresencePalette() == PALETTE_NOK)
				{
					//ecriture à BAL_versErreur 
					msgErreur.source=T_PALETTE;
					msgErreur.message=PALETTE_ABS;
					msgErreur.heure=time(NULL);
					msgErreur.numLot=numLotImp;
					msgErreur.cartonEnCours=numCartonImp;

					//envoi du message msgPaletteOK à Erreur
					if (0 != mq_send(queue_versErreur,(const char*)&msgErreur,sizeof(MSG_versErreur),msgPrio))
					{
						   perror ("[Palette] Failed to Send BAL_versErreur:");
						   		
					}
	
					// Attente du compte rendu Erreur 
					bytes_read = mq_receive(queue_retErreur,(char*)&msgRetErreur,sizeof(MSG_retErreur),NULL);
					if (bytes_read == -1)
					{
					  	perror("[Palette] Failed to recieve BAL_retErreur:");
					}
					else
					{
						if (msgRetErreur.reponse == FIN_APPLI)
						{
							flagReprise=0;
							//ecriture du message de FIN_APPLI à stockage
							msgErreurImp.type=FIN_APPLI;
							msgErreurImp.numCarton=0;
							msgErreurImp.numLot=numLotImp;
							msgErreurImp.typeProduit=typeProduitImp;

							//envoi du message FIN_APPLI à Stockage
							if (0 != mq_send(queue_versStockage,(const char*)&msgErreurImp,sizeof(MSG_carton),msgPrio))
							{
								perror ("[Palette] Failed to Send BAL_versStockage:");

							}
					

							//Fermeture des BAL
							mq_close (queue_versArchivage);
							mq_close (queue_versPalette); 
							mq_close (queue_versStockage); 
							mq_close (queue_versErreur);
							mq_close (queue_retErreur);
							pthread_exit(NULL);
				

						} // fin if FIN_APPLI

					} //fin if attente erreur
			
				} // fin if PRESENCE_NOK

			} //fin if nbCartonMisEnPalette==0

		} //fin if FIN_APPLI || FIN_PROD


		//flagReprise = 1 si palette presente
		if (flagReprise == 1)
		{
			//mise du carton en palette
			nbCartonMisEnPalette+=1;

			//Verif place palette A
			if (typeProduitImp == 'A')
			{
				//Lecture de la capacité de la palette dans la mem Partagee
				pthread_mutex_lock(MutexSHMOF);
				capacitePalette=OrdreFabrication->taillePaletteA;
				pthread_mutex_unlock(MutexSHMOF);
				
				nbPlace=capacitePalette-nbCartonMisEnPalette;
				//if palette pleine
				if (nbPlace==0)
				{

					//ecriture du message msgPaletteOK
					msgPaletteOK.type=CARTON;
					msgPaletteOK.numCarton=0;
					msgPaletteOK.numLot=numLotImp;
					msgPaletteOK.typeProduit='A';

					//envoi du message msgPaletteOK à Stockage
					if (0 != mq_send(queue_versStockage,(const char*)&msgPaletteOK,sizeof(MSG_carton),msgPrio))
					{
					   	perror ("[Palette] Failed to Send BAL_versStockage:");

					}

					//ecriture du message msgPalette_archivage
					msgPalette_archivage.source=T_PALETTE;
					msgPalette_archivage.message=PAL_OK;
					msgPalette_archivage.heure=time(NULL);
					msgPalette_archivage.numLot=numLotImp;
					msgPalette_archivage.cartonEnCours=0;
					msgPalette_archivage.type=ARCHIVAGE;

					//envoi du message msgPalette_archivage à Archivage
					if (0 != mq_send(queue_versArchivage,(const char*)&msgPalette_archivage,sizeof(MSG_versArchivage),msgPrio))
					{
					   	perror ("[Palette] Failed to Send BAL_versArchivage:");
		
					}
					#ifdef DEBUG
					printf("[PALETTE] Palette A envoye a stockage \n");
					#endif
					//nouvelle palette
					nbCartonMisEnPalette=0;

				} // fin if palette pleine

			}
			else
			{
				//Verif place palette B
				if (typeProduitImp == 'B')
				{
					//Lecture de la capacité de la palette dans la mem Partagee
					pthread_mutex_lock(MutexSHMOF);
					capacitePalette=OrdreFabrication->taillePaletteB;
					pthread_mutex_unlock(MutexSHMOF);
					
					nbPlace=capacitePalette-nbCartonMisEnPalette;
					//if palette pleine
					if (nbPlace==0)
					{

						//ecriture du message msgPaletteOK
						msgPaletteOK.type=CARTON;
						msgPaletteOK.numCarton=0;
						msgPaletteOK.numLot=numLotImp;
						msgPaletteOK.typeProduit='B';

						//envoi du message msgPaletteOK à Stockage
						if (0 != mq_send(queue_versStockage,(const char*)&msgPaletteOK,sizeof(MSG_carton),msgPrio))
						{
					   		perror ("[Palette] Failed to Send BAL_versStockage:");
					   		
						}


						//ecriture du message msgPalette_archivage
						msgPalette_archivage.source=T_PALETTE;
						msgPalette_archivage.message=PAL_OK;
						msgPalette_archivage.heure=time(NULL);
						msgPalette_archivage.numLot=numLotImp;
						msgPalette_archivage.cartonEnCours=0;
						msgPalette_archivage.type=ARCHIVAGE;

						//envoi du message msgPalette_archivage à Archivage
						if (0 != mq_send(queue_versArchivage,(const char*)&msgPalette_archivage,sizeof(MSG_versArchivage),msgPrio))
						{
					   		perror ("[Palette] Failed to Send BAL_versArchivage:");
					   			
						}
						#ifdef DEBUG
						printf("[PALETTE] Palette B envoye a stockage \n");
						#endif
						//nouvelle palette
						nbCartonMisEnPalette=0;

					} // fin if palette pleine B

				} //fin if typeProduit B

			} //fin if typeProduit A

		} //fin if flag reprise



	  } //fin if reception queue_versPalette


	} 
	//-------------------------------FIN Phase moteur--------------------------



} //fin procedure

